/*
PearReview - The peer review assistant.
Copyright (C) 2009  Dimitrij Pankratz, Anton Musichin
http://www.pearreview.com, info@pearreview.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package com.pearreview.application;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Locale;

import javax.swing.*;
import javax.swing.border.*;
import com.pearreview.ui.*;
import com.pearreview.ui.list.LocaleListCellRenderer;

public class PreferencesBox extends EscapeDialog {
	private static final long serialVersionUID = 8871016399579683461L;
	
	private static final String[] SAVE_OPTIONS = {
		getLocalizedString("autosave.never"), 
		"3 " + getLocalizedString("autosave.minuts"), 
		"5 " + getLocalizedString("autosave.minuts"), 
		"10 " + getLocalizedString("autosave.minuts"), 
		"15 " + getLocalizedString("autosave.minuts")
	};
	private static final Long[] SAVE_OPTIONS_VALUES = {
		-1L, 
		3L * 60L * 1000L, 
		5L * 60L * 1000L, 
		10L * 60L * 1000L, 
		15L * 60L * 1000L
	};
	
	private JPanel dialogPane;
	private JPanel contentPanel;
	private FormLabel caption;
	private FormLabel languageLabel;
	private JComboBox language;
	private FormLabel autoSaveLabel;
	private JComboBox autoSave;
	private FormLabel workspaceLabel;
	private FormLabel workspace;
	private FormLabel updateLabel;
	private JCheckBox update;
	private FormLabel sessionLabel;
	private JCheckBox session;
	private FormLabel fullScreenModeLabel;
	private JCheckBox fullScreenMode;
	private JButton workspaceBtn;
	private JPanel buttonBar;
	private JButton saveBtn;
	private JButton abortBtn;
	
	private File workspaceFile;
	
	private Locale[] lang;
	
	private Preferences oldPreferences;
	private Preferences newPreferences;
	
	public PreferencesBox(Frame owner, Locale[] lang) {
		super(owner, true);
		this.lang = lang;
		initComponents();
	}

	public PreferencesBox(Dialog owner, Locale[] lang) {
		super(owner, true);
		this.lang = lang;
		initComponents();
	}
	
	/**
	 * Returns localized string of this component
	 * @param key key of string to localize
	 * @return localized string of this component
	 */
	private static String getLocalizedString(String key) {
		return Messages.getString("PearReview.preferences." + key);
	}
	
	/**
	 * Sets workspace path
	 * @param ws workspace path to set
	 */
	public void setWorkspace(File ws) {
		workspaceFile = ws;
		if(ws != null && ws.exists() && ws.isDirectory()) {
			workspace.setFont(workspace.getFont().deriveFont(Font.PLAIN));
			workspace.setToolTipText(workspaceFile.getAbsolutePath());
			workspace.setText(workspaceFile.toString());
			workspaceBtn.setEnabled(true);
		} else {
			workspace.setFont(workspace.getFont().deriveFont(Font.ITALIC));
			workspace.setToolTipText(null);
			workspace.setText(getLocalizedString("workspace.not_exists"));
			workspaceBtn.setEnabled(false);
		}
	}

	private void initComponents() {
		setTitle(getLocalizedString("title"));
		
		dialogPane = new PearPanel();
		contentPanel = new JPanel();
		caption = new FormLabel();
		languageLabel = new FormLabel();
		language = new JComboBox(lang);
		autoSaveLabel = new FormLabel();
		autoSave = new JComboBox(SAVE_OPTIONS);
		workspaceLabel = new FormLabel();
		workspace = new FormLabel();
		workspaceBtn = new JButton();
		updateLabel = new FormLabel();
		update = new JCheckBox();
		sessionLabel = new FormLabel();
		session = new JCheckBox();
		fullScreenModeLabel = new FormLabel();
		fullScreenMode = new JCheckBox();
		buttonBar = new JPanel();
		saveBtn = new JButton();
		abortBtn = new JButton();
		
		ToolTipManager.sharedInstance()
				.registerComponent(workspace);
		
		language.setRenderer(new LocaleListCellRenderer());

		//======== this ========
		Container contentPane = getContentPane();
		contentPane.setLayout(new BorderLayout());
		setResizable(false);
		setDefaultCloseOperation(DISPOSE_ON_CLOSE);

		//======== dialogPane ========
		{
			dialogPane.setBorder(new EmptyBorder(12, 12, 12, 12));
			dialogPane.setLayout(new BorderLayout());

			//======== contentPanel ========
			{

				//---- caption ----
				caption.setText(getLocalizedString("caption"));
				caption.setFont(new Font("Tahoma", Font.PLAIN, 14));

				//---- languageLabel ----
				languageLabel.setText(getLocalizedString("language"));

				//---- autoSaveLabel ----
				autoSaveLabel.setText(getLocalizedString("autosave"));

				//---- workspaceLabel ----
				workspaceLabel.setText(getLocalizedString("workspace"));
				
				//---- workspace ----
				workspace.setText("");
				
				//---- updateLabel ----
				updateLabel.setText(getLocalizedString("update"));
				
				//---- sessionLabel ----
				sessionLabel.setText(getLocalizedString("session"));
				
				//---- fullScreenModeLabel ----
				fullScreenModeLabel.setText(getLocalizedString("full_screen"));
				
				//---- update ----
				update.setOpaque(false);
				
				//---- session ----
				session.setOpaque(false);
				
				//---- fullScreenMode ----
				fullScreenMode.setOpaque(false);

				//---- workspaceBtn ----
				workspaceBtn.setText(getLocalizedString("open"));
				workspaceBtn.addActionListener(new OpenWorkspaceAction());
				
				contentPanel.setOpaque(false);

				GroupLayout contentPanelLayout = new GroupLayout(contentPanel);
				contentPanel.setLayout(contentPanelLayout);
				contentPanelLayout.setHorizontalGroup(
					contentPanelLayout.createParallelGroup()
						.addGroup(contentPanelLayout.createSequentialGroup()
							.addContainerGap()
							.addGroup(contentPanelLayout.createParallelGroup()
								.addComponent(caption, 
										GroupLayout.PREFERRED_SIZE, 
										GroupLayout.DEFAULT_SIZE, 
										GroupLayout.PREFERRED_SIZE)
								.addGroup(contentPanelLayout
										.createSequentialGroup()
									.addGroup(contentPanelLayout
											.createParallelGroup()
										.addComponent(languageLabel, 
												GroupLayout.PREFERRED_SIZE, 
												GroupLayout.DEFAULT_SIZE, 
												GroupLayout.PREFERRED_SIZE)
										.addComponent(autoSaveLabel, 
												GroupLayout.PREFERRED_SIZE, 
												GroupLayout.DEFAULT_SIZE, 
												GroupLayout.PREFERRED_SIZE)
										.addComponent(workspaceLabel, 
												GroupLayout.PREFERRED_SIZE, 
												GroupLayout.DEFAULT_SIZE, 
												GroupLayout.PREFERRED_SIZE)
										.addComponent(updateLabel, 
												GroupLayout.PREFERRED_SIZE, 
												GroupLayout.DEFAULT_SIZE, 
												GroupLayout.PREFERRED_SIZE)
										.addComponent(sessionLabel, 
													GroupLayout.PREFERRED_SIZE, 
													GroupLayout.DEFAULT_SIZE, 
													GroupLayout.PREFERRED_SIZE)
										.addComponent(fullScreenModeLabel, 
													GroupLayout.PREFERRED_SIZE, 
													GroupLayout.DEFAULT_SIZE, 
													GroupLayout.PREFERRED_SIZE))
									.addGap(88, 88, 88)
									.addGroup(contentPanelLayout
											.createParallelGroup()
										.addComponent(autoSave, 
												GroupLayout.DEFAULT_SIZE, 
												300, 
												Short.MAX_VALUE)
										.addGroup(contentPanelLayout
												.createSequentialGroup()
											.addComponent(workspace, 
													GroupLayout.PREFERRED_SIZE, 
													200, 
													Short.MAX_VALUE)
											.addPreferredGap(LayoutStyle
												.ComponentPlacement.RELATED)
											.addComponent(workspaceBtn, 
													GroupLayout.DEFAULT_SIZE, 
													GroupLayout.PREFERRED_SIZE, 
													Short.MAX_VALUE))
										.addComponent(language, 
												GroupLayout.PREFERRED_SIZE, 
												300, 
												Short.MAX_VALUE)
										.addComponent(update, 
													GroupLayout.PREFERRED_SIZE, 
													300, 
													Short.MAX_VALUE)
										.addComponent(session, 
													GroupLayout.PREFERRED_SIZE, 
													300, 
													Short.MAX_VALUE)
										.addComponent(fullScreenMode, 
													GroupLayout.PREFERRED_SIZE, 
													300, 
													Short.MAX_VALUE))))
							.addGap(75, 75, 75))
				);
				contentPanelLayout.setVerticalGroup(
					contentPanelLayout.createParallelGroup()
						.addGroup(contentPanelLayout.createSequentialGroup()
							.addContainerGap()
							.addComponent(caption, 
									GroupLayout.PREFERRED_SIZE, 
									GroupLayout.DEFAULT_SIZE, 
									GroupLayout.PREFERRED_SIZE)
							.addGap(18, 18, 18)
							.addGroup(contentPanelLayout.createParallelGroup()
								.addComponent(languageLabel, 
										GroupLayout.PREFERRED_SIZE, 
										GroupLayout.DEFAULT_SIZE, 
										GroupLayout.PREFERRED_SIZE)
								.addComponent(language, 
										GroupLayout.PREFERRED_SIZE, 
										GroupLayout.DEFAULT_SIZE, 
										GroupLayout.PREFERRED_SIZE))
							.addPreferredGap(LayoutStyle
									.ComponentPlacement.RELATED)
							.addGroup(contentPanelLayout.createParallelGroup()
								.addComponent(autoSaveLabel, 
										GroupLayout.PREFERRED_SIZE, 
										GroupLayout.DEFAULT_SIZE, 
										GroupLayout.PREFERRED_SIZE)
								.addComponent(autoSave, 
										GroupLayout.PREFERRED_SIZE, 
										GroupLayout.DEFAULT_SIZE, 
										GroupLayout.PREFERRED_SIZE))
							.addPreferredGap(LayoutStyle
									.ComponentPlacement.RELATED)
							.addGroup(contentPanelLayout.createParallelGroup()
								.addComponent(workspaceLabel, 
										GroupLayout.PREFERRED_SIZE, 
										GroupLayout.DEFAULT_SIZE, 
										GroupLayout.PREFERRED_SIZE)
								.addComponent(workspace, 
										GroupLayout.PREFERRED_SIZE, 
										GroupLayout.DEFAULT_SIZE, 
										GroupLayout.PREFERRED_SIZE)
								.addComponent(workspaceBtn))
							.addPreferredGap(LayoutStyle
									.ComponentPlacement.RELATED)
							.addGroup(contentPanelLayout.createParallelGroup()
								.addComponent(updateLabel, 
										GroupLayout.PREFERRED_SIZE, 
										GroupLayout.DEFAULT_SIZE, 
										GroupLayout.PREFERRED_SIZE)
								.addComponent(update, 
										GroupLayout.PREFERRED_SIZE, 
										GroupLayout.DEFAULT_SIZE, 
										GroupLayout.PREFERRED_SIZE))
							.addPreferredGap(LayoutStyle
									.ComponentPlacement.RELATED)
							.addGroup(contentPanelLayout.createParallelGroup()
								.addComponent(sessionLabel, 
										GroupLayout.PREFERRED_SIZE, 
										GroupLayout.DEFAULT_SIZE, 
										GroupLayout.PREFERRED_SIZE)
								.addComponent(session, 
										GroupLayout.PREFERRED_SIZE, 
										GroupLayout.DEFAULT_SIZE, 
										GroupLayout.PREFERRED_SIZE))
							.addPreferredGap(LayoutStyle
									.ComponentPlacement.RELATED)
							.addGroup(contentPanelLayout.createParallelGroup()
								.addComponent(fullScreenModeLabel, 
										GroupLayout.PREFERRED_SIZE, 
										GroupLayout.DEFAULT_SIZE, 
										GroupLayout.PREFERRED_SIZE)
								.addComponent(fullScreenMode, 
										GroupLayout.PREFERRED_SIZE, 
										GroupLayout.DEFAULT_SIZE, 
										GroupLayout.PREFERRED_SIZE))
							.addContainerGap(20, Short.MAX_VALUE))
				);
			}
			dialogPane.add(contentPanel, BorderLayout.CENTER);

			//======== buttonBar ========
			{
				buttonBar.setBorder(new EmptyBorder(12, 0, 0, 0));
				buttonBar.setOpaque(false);

				//---- saveBtn ----
				saveBtn.setText(getLocalizedString("save"));
				saveBtn.addActionListener(new ApplyAction());

				//---- abortBtn ----
				abortBtn.setText(getLocalizedString("abort"));
				abortBtn.addActionListener(new AbortAction());

				GroupLayout buttonBarLayout = new GroupLayout(buttonBar);
				buttonBar.setLayout(buttonBarLayout);
				buttonBarLayout.setHorizontalGroup(
					buttonBarLayout.createParallelGroup()
						.addGroup(GroupLayout.Alignment.TRAILING, 
								buttonBarLayout.createSequentialGroup()
							.addContainerGap()
							.addComponent(saveBtn)
							.addPreferredGap(LayoutStyle
									.ComponentPlacement.RELATED)
							.addComponent(abortBtn))
				);
				buttonBarLayout.setVerticalGroup(
					buttonBarLayout.createParallelGroup()
						.addGroup(buttonBarLayout.createSequentialGroup()
							.addGroup(buttonBarLayout
									.createParallelGroup(
											GroupLayout.Alignment.BASELINE)
								.addComponent(abortBtn)
								.addComponent(saveBtn))
							.addContainerGap(
									GroupLayout.DEFAULT_SIZE, 
									Short.MAX_VALUE))
				);
			}
			dialogPane.add(buttonBar, BorderLayout.SOUTH);
		}
		contentPane.add(dialogPane, BorderLayout.CENTER);
		pack();
		setLocationRelativeTo(getOwner());
	}
	
	public void setDefaultPreferences(Preferences preferences) {
		setPreferences(preferences);
	}
	
	public void setPreferences(Preferences preferences) {
		this.oldPreferences = preferences;
		this.newPreferences = null;
		
		Object sessionOption = preferences.getValue(
				Preferences.SESSION_OPTION_KEY);
		Object updateOption = preferences.getValue(
				Preferences.UPDATE_OPTION_KEY);
		Object fullScreenOption = preferences.getValue(
				Preferences.FULL_SCREEN_OPTION_KEY);
		Object locale = preferences.getValue(
				Preferences.LOCALE_KEY);
		Object interval = preferences.getValue(
				Preferences.SAVE_INTERVAL_KEY);
		
		language.setSelectedItem(locale);
		
		if(sessionOption != null) {
			session.setSelected(Boolean.TRUE.equals(sessionOption));
		}
		if(updateOption != null) {
			update.setSelected(Boolean.TRUE.equals(updateOption));
		}
		if(fullScreenOption != null) {
			fullScreenMode.setSelected(Boolean.TRUE.equals(fullScreenOption));
		}
		if(interval != null) {
			long lInterval = -1;
			if(interval instanceof Long){
				lInterval = (Long) interval;
			}
			
			int index = Arrays.asList(SAVE_OPTIONS_VALUES).indexOf(lInterval);
			if(index >= 0)
				autoSave.setSelectedIndex(index);
			else if (lInterval < 0) {
				autoSave.setSelectedIndex(0);
			} else {
				autoSave.setSelectedIndex(SAVE_OPTIONS_VALUES.length - 1);
				for(int i = 1 ; i < SAVE_OPTIONS_VALUES.length ; i++) {
					if(lInterval <= SAVE_OPTIONS_VALUES[i]) {
						autoSave.setSelectedIndex(i);
						break;
					}
				}
			}
		}
	}
	
	/**
	 * Returns preferences.
	 * @return preferences if user clicked apply, otherwise <code>null</code>.
	 */
	public Preferences getPreferences() {
		return newPreferences;
	}

	private class OpenWorkspaceAction implements ActionListener, Serializable {
		private static final long serialVersionUID = -8489028732707979089L;
		@Override
		public void actionPerformed(ActionEvent event) {
			setWorkspace(workspaceFile);
			try {
				if(workspaceFile != null && workspaceFile.exists()) {
					Desktop.getDesktop().browse(workspaceFile.toURI());
				}
			} catch (IOException e) {
				// TODO error message?!
				e.printStackTrace();
			}
		}
	}
	
	private class AbortAction implements ActionListener, Serializable {
		private static final long serialVersionUID = 5441990829023393167L;
		@Override
		public void actionPerformed(ActionEvent event) {
			dispose();
		}
	}
	
	private class ApplyAction implements ActionListener, Serializable {
		private static final long serialVersionUID = 5131331917713706358L;
		@Override
		public void actionPerformed(ActionEvent event) {
			Locale selectedLocale = (Locale)language.getSelectedItem();
			
			newPreferences = new Preferences(oldPreferences);
			
			if(oldPreferences != null) {
				Object oldLocale = 
					oldPreferences.getValue(Preferences.LOCALE_KEY);
				if(!selectedLocale.equals(oldLocale)) {
					JOptionPane.showMessageDialog(PreferencesBox.this, 
							getLocalizedString("warning.language"), 
							getLocalizedString("warning.language.title"), 
							JOptionPane.WARNING_MESSAGE);
				}
			}
			int selectedOption = autoSave.getSelectedIndex();
			
			newPreferences.putValue(Preferences.LOCALE_KEY, selectedLocale);
			newPreferences.putValue(Preferences.SAVE_INTERVAL_KEY, 
					SAVE_OPTIONS_VALUES[selectedOption]);
			newPreferences.putValue(Preferences.SESSION_OPTION_KEY, 
					session.isSelected());
			newPreferences.putValue(Preferences.UPDATE_OPTION_KEY, 
					update.isSelected());
			newPreferences.putValue(Preferences.FULL_SCREEN_OPTION_KEY, 
					fullScreenMode.isSelected());
			
			dispose();
		}
	}
}
